package com.xuecheng.learning.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xuecheng.base.exception.XueChengPlusException;
import com.xuecheng.base.model.PageResult;
import com.xuecheng.content.model.po.CoursePublish;
import com.xuecheng.learning.feignclient.ContentServiceClient;
import com.xuecheng.learning.mapper.XcChooseCourseMapper;
import com.xuecheng.learning.mapper.XcCourseTablesMapper;
import com.xuecheng.learning.model.dto.MyCourseTableParams;
import com.xuecheng.learning.model.dto.XcChooseCourseDto;
import com.xuecheng.learning.model.dto.XcCourseTablesDto;
import com.xuecheng.learning.model.po.XcChooseCourse;
import com.xuecheng.learning.model.po.XcCourseTables;
import com.xuecheng.learning.service.MyCourseTablesService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 选课相关接口实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MyCourseTablesServiceImpl implements MyCourseTablesService {

    private final XcChooseCourseMapper xcChooseCourseMapper; // 选课相关

    private final XcCourseTablesMapper xcCourseTablesMapper; // 我的课程表

    private final ContentServiceClient contentServiceClient;

    /**
     * 添加选课
     *
     * @param userId   用户id
     * @param courseId 课程id
     * @return 选课记录对象
     */
    @Transactional
    @Override
    public XcChooseCourseDto addChooseCourse(String userId, Long courseId) {
        // 远程调用内容管理服务查询课程的收费规则
        CoursePublish coursepublish = contentServiceClient.getCoursepublish(courseId);
        if (coursepublish == null) {
            XueChengPlusException.cast("课程信息不存在");
        }

        // 获取课程的收费规则
        String charge = coursepublish.getCharge();

        // 选课记录
        XcChooseCourse xcChooseCourse = null;
        if ("201000".equals(charge)) { // 免费课程
            // 如果是免费课程 会向课程记录表
            xcChooseCourse = addFreeCourse(userId, coursepublish); // 向课程记录表写
            // 向我的课程表写数据
            XcCourseTables xcCourseTables = addCourseTables(xcChooseCourse);
        } else {
            // 如果是收费课程 会向选课记录表写数据
            xcChooseCourse = addChargeCourse(userId, coursepublish);
        }

        // 判断学生的学习资格
        XcCourseTablesDto xcCourseTablesDto = getLearningStatus(userId, courseId);

        // 构建返回值
        XcChooseCourseDto xcChooseCourseDto = new XcChooseCourseDto();
        BeanUtils.copyProperties(xcChooseCourse, xcChooseCourseDto);

        // 设置学习资格状态
        xcChooseCourseDto.setLearnStatus(xcCourseTablesDto.getLearnStatus());

        return xcChooseCourseDto;
    }

    /**
     * 判断学习资格
     *
     * @param userId   用户id
     * @param courseId 课程id
     * @return 学习资格状态
     */
    @Override
    public XcCourseTablesDto getLearningStatus(String userId, Long courseId) {
        // 最终返回的数据
        XcCourseTablesDto courseTablesDto = new XcCourseTablesDto();
        // [{"code":"702001","desc":"正常学习"},{"code":"702002","desc":"没有选课或选课后没有支付"},{"code":"702003","desc":"已过期需要申请续期或重新支付"}]
        // 查询我的课程表，如果查不到说明没有选课
        XcCourseTables xcCourseTables = getXcCourseTables(userId, courseId);
        if (courseId == null) {
            courseTablesDto.setLearnStatus("702002");
            return courseTablesDto;
        }

        // 如果查到了判断是否过期 如果过期就不能学习了
        // 如果截至日志在当前时间之前 说明过期了
        boolean before = xcCourseTables.getValidtimeEnd().isBefore(LocalDateTime.now());
        if (before) {
            // 过期的情况
            BeanUtils.copyProperties(xcCourseTables, courseTablesDto);
            courseTablesDto.setLearnStatus("702003");
            return courseTablesDto;
        } else {
            // 正常情况
            BeanUtils.copyProperties(xcCourseTables, courseTablesDto);
            courseTablesDto.setLearnStatus("702001");
            return courseTablesDto;
        }
    }

    /**
     * 保存选课成功
     *
     * @param chooseCourseId 选课id
     * @return 返回true 表示保存成功 false表示保存失败
     */
    @Override
    public boolean saveChooseCourseSuccess(String chooseCourseId) {
        // 根据选课id查询选课表
        XcChooseCourse chooseCourse = xcChooseCourseMapper.selectById(chooseCourseId);
        if (chooseCourse == null) {
            log.debug("接收购买课程的信息，根据选课id从数据库找不到选课记录 选课id{}", chooseCourseId);
            return false;
        }

        // 获取选课状态
        String status = chooseCourse.getStatus();
        // 只有选课状态为未支付更新为已支付
        if ("701002".equals(status)) {
            // 更新选课的记录为支付成功
            chooseCourse.setStatus("701001");
            int i = xcChooseCourseMapper.updateById(chooseCourse);
            if (i <= 0) {
                log.debug("更新选课记录失败 选课id{}", chooseCourseId);
                XueChengPlusException.cast("更新选课记录失败");
            }
            // 向我的课程表插入记录
            XcCourseTables xcCourseTables = addCourseTables(chooseCourse);
            return true;
        }
        return false;
    }

    /**
     * 查询我的课程表
     *
     * @param params 查询参数
     * @return 课程表信息
     */
    @Override
    public PageResult<XcCourseTables> myCourseTables(MyCourseTableParams params) {
        // 获取用户id
        String userId = params.getUserId();
        // 获取当前页码
        int pageNo = params.getPage();
        // 获取每页记录数
        int pageSize = params.getSize();

        Page<XcCourseTables> courseTablesPage = new Page<>(pageNo, pageSize);

        Page<XcCourseTables> result = xcCourseTablesMapper.selectPage(courseTablesPage, new LambdaQueryWrapper<XcCourseTables>().eq(XcCourseTables::getUserId, userId));

        // 总记录数
        long total = result.getTotal();
        // 数据集合
        List<XcCourseTables> records = result.getRecords();

        return new PageResult<>(records, total, pageNo, pageSize);
    }

    /**
     * 添加免费课程,免费课程加入选课记录表、我的课程表
     *
     * @param userId        用户id
     * @param coursePublish 课程发布信息
     * @return 选课信息
     */
    public XcChooseCourse addFreeCourse(String userId, CoursePublish coursePublish) {
        // 获取课程id 课程发布表的主键就是课程id
        Long courseId = coursePublish.getId();

        // 判断如果存在免费的选课记录且选课状态为成功 直接返回
        LambdaQueryWrapper<XcChooseCourse> queryWrapper = new LambdaQueryWrapper<XcChooseCourse>()
                .eq(XcChooseCourse::getUserId, userId)
                .eq(XcChooseCourse::getCourseId, courseId)
                .eq(XcChooseCourse::getOrderType, "700001") // "700001" 表示免费课程
                .eq(XcChooseCourse::getStatus, "701001"); // "701001" 表示选课成功

        // 因为可能存在多个数据 所以返回的是一个list集合
        List<XcChooseCourse> xcChooseCourses = xcChooseCourseMapper.selectList(queryWrapper);
        if (!xcChooseCourses.isEmpty()) {
            // 如果存在数据 直接返回第一个数据即可
            return xcChooseCourses.get(0);
        }

        // 向选课记录表写数据
        XcChooseCourse xcChooseCourse = new XcChooseCourse();
        xcChooseCourse.setCourseId(coursePublish.getId());
        xcChooseCourse.setCourseName(coursePublish.getName());
        xcChooseCourse.setCoursePrice(0f); // 免费课程价格为0
        xcChooseCourse.setUserId(userId);
        xcChooseCourse.setCompanyId(coursePublish.getCompanyId());
        xcChooseCourse.setOrderType("700001"); // 免费课程
        xcChooseCourse.setCreateDate(LocalDateTime.now());
        xcChooseCourse.setStatus("701001"); // 选课成功
        xcChooseCourse.setValidDays(365); // 免费课程默认365
        xcChooseCourse.setValidtimeStart(LocalDateTime.now()); // 课程有效期开始时间
        xcChooseCourse.setValidtimeEnd(LocalDateTime.now().plusDays(365)); // 课程有效期结束时间

        // 插入数据
        int insert = xcChooseCourseMapper.insert(xcChooseCourse);
        if (insert <= 0) {
            XueChengPlusException.cast("添加选课记录失败");
        }

        return xcChooseCourse;
    }

    /**
     * 添加到我的课程表
     *
     * @param xcChooseCourse 选课记录
     * @return 课程表信息
     */
    public XcCourseTables addCourseTables(XcChooseCourse xcChooseCourse) {
        // 只有选课成功了才可以向我的课程表添加数据
        String status = xcChooseCourse.getStatus();
        if (!"701001".equals(status)) {
            XueChengPlusException.cast("选课没有成功无法添加到课程表");
        }

        XcCourseTables xcCourseTables = getXcCourseTables(xcChooseCourse.getUserId(), xcChooseCourse.getCourseId());
        // 判断是否添加过课程表信息 如果已经添加过了直接返回
        if (xcCourseTables != null) {
            return xcCourseTables;
        }

        xcCourseTables = new XcCourseTables();
        BeanUtils.copyProperties(xcChooseCourse, xcCourseTables);
        xcCourseTables.setChooseCourseId(xcChooseCourse.getId()); // 记录选课表的主键
        xcCourseTables.setCourseType(xcChooseCourse.getOrderType()); // 选课类型
        xcCourseTables.setUpdateDate(LocalDateTime.now());

        // 插入数据
        int insert = xcCourseTablesMapper.insert(xcCourseTables);
        if (insert <= 0) {
            XueChengPlusException.cast("添加到我的课程表失败");
        }

        return xcCourseTables;
    }

    /**
     * 添加收费课程
     *
     * @param userId        用户id
     * @param coursePublish 课程发布信息
     * @return 选课信息
     */
    public XcChooseCourse addChargeCourse(String userId, CoursePublish coursePublish) {
        // 获取课程id 课程发布表的主键就是课程id
        Long courseId = coursePublish.getId();

        // 判断如果存在收费的选课记录且选课状态为待支付 直接返回
        LambdaQueryWrapper<XcChooseCourse> queryWrapper = new LambdaQueryWrapper<XcChooseCourse>()
                .eq(XcChooseCourse::getUserId, userId)
                .eq(XcChooseCourse::getCourseId, courseId)
                .eq(XcChooseCourse::getOrderType, "700002") // "700002" 表示收费课程
                .eq(XcChooseCourse::getStatus, "701002"); // "701001" 表示待支付

        // 因为可能存在多个数据 所以返回的是一个list集合
        List<XcChooseCourse> xcChooseCourses = xcChooseCourseMapper.selectList(queryWrapper);
        if (!xcChooseCourses.isEmpty()) {
            // 如果存在数据 直接返回第一个数据即可
            return xcChooseCourses.get(0);
        }

        // 向选课记录表写数据
        XcChooseCourse xcChooseCourse = new XcChooseCourse();
        xcChooseCourse.setCourseId(coursePublish.getId());
        xcChooseCourse.setCourseName(coursePublish.getName());
        xcChooseCourse.setCoursePrice(0f); // 免费课程价格为0
        xcChooseCourse.setUserId(userId);
        xcChooseCourse.setCompanyId(coursePublish.getCompanyId());
        xcChooseCourse.setOrderType("700002"); // 收费课程
        xcChooseCourse.setCreateDate(LocalDateTime.now());
        xcChooseCourse.setStatus("701002"); // 待支付
        xcChooseCourse.setValidDays(365); // 免费课程默认365
        xcChooseCourse.setValidtimeStart(LocalDateTime.now()); // 课程有效期开始时间
        xcChooseCourse.setValidtimeEnd(LocalDateTime.now().plusDays(365)); // 课程有效期结束时间

        // 插入数据
        int insert = xcChooseCourseMapper.insert(xcChooseCourse);
        if (insert <= 0) {
            XueChengPlusException.cast("添加选课记录失败");
        }

        return xcChooseCourse;
    }

    /**
     * 根据课程和用户查询我的课程表中某一门课程
     *
     * @param userId   用户id
     * @param courseId 课程id
     * @return 课程表信息
     */
    public XcCourseTables getXcCourseTables(String userId, Long courseId) {
        return xcCourseTablesMapper.selectOne(new LambdaQueryWrapper<XcCourseTables>()
                .eq(XcCourseTables::getUserId, userId)
                .eq(XcCourseTables::getCourseId, courseId));
    }
}
